/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "imageknife_task_internal.h"
#include "imageknife_internal.h"
#include "request/imageknife_request_internal.h"
#include <multimedia/image_framework/image/image_source_native.h>

namespace ImageKnifeC {

std::string ImageKnifeTaskInternal::GetTaskInfo(ImageRequestType type, ImageKnifeRequest *request)
{
    if (request == nullptr) {
        return "[Null Request] ";
    }
    auto internalRequest = dynamic_cast<ImageKnifeRequestInternal *>(request);
    if (internalRequest == nullptr) {
        return "get request failed";
    }

    std::string source;
    switch (type) {
        case ImageRequestType::MAIN_SRC:
            source = "MainSrc";
            break;
        case ImageRequestType::PLACE_SRC:
            source = "PlaceSrc";
            break;
        case ImageRequestType::ERROR_SRC:
            source = "ErrorSrc";
            break;
        default:
            break;
    }
    return "[ID:" + internalRequest->GetNodeId() + " VersionID:" + std::to_string(internalRequest->GetVersion()) +
           " Type:" + source + "] ";
}

// TODO 该函数功能由请求数据采集部分 替换,该函数或被废弃
void ImageKnifeTaskInternal::QueryDisplayPixelmapInfo()
{
    if (product.imageData == nullptr || product.imageData->GetPixelmap() == nullptr) {
        return;
    }

    OH_Pixelmap_ImageInfo* imageInfo = nullptr;
    if (OH_PixelmapImageInfo_Create(&imageInfo) != IMAGE_SUCCESS) {
        return;
    }

    if (OH_PixelmapNative_GetImageInfo(product.imageData->GetPixelmap(), imageInfo) != IMAGE_SUCCESS) {
        return;
    }

    int32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
    OH_PixelmapImageInfo_GetWidth(imageInfo, &pixelmapInfo.width);
    OH_PixelmapImageInfo_GetHeight(imageInfo, &pixelmapInfo.height);
    OH_PixelmapImageInfo_GetPixelFormat(imageInfo, &pixelFormat);
    OH_PixelmapImageInfo_Release(imageInfo);
    const int half = 2;
    const int four = 4;
    if (pixelFormat == PIXEL_FORMAT_NV21 || pixelFormat == PIXEL_FORMAT_NV12) {
        pixelmapInfo.size = pixelmapInfo.width * pixelmapInfo.height +
                            ((pixelmapInfo.width + 1) / half) * ((pixelmapInfo.height + 1) / half) * half;
    } else {
        pixelmapInfo.size = pixelmapInfo.width * pixelmapInfo.height * four;
    }

    switch (pixelFormat) {
        case PIXEL_FORMAT_RGB_565 :
            pixelmapInfo.pixelFormat = "RGB_565";
            break;
        case PIXEL_FORMAT_RGBA_8888 :
            pixelmapInfo.pixelFormat = "RGBA_8888";
            break;
        case PIXEL_FORMAT_BGRA_8888 :
            pixelmapInfo.pixelFormat = "BGRA_8888";
            break;
        case PIXEL_FORMAT_RGB_888 :
            pixelmapInfo.pixelFormat = "RGB_888";
            break;
        case PIXEL_FORMAT_ALPHA_8 :
            pixelmapInfo.pixelFormat = "ALPHA_8";
            break;
        case PIXEL_FORMAT_RGBA_F16 :
            pixelmapInfo.pixelFormat = "RGBA_F16";
            break;
        case PIXEL_FORMAT_NV21 :
            pixelmapInfo.pixelFormat = "NV21";
            break;
        case PIXEL_FORMAT_NV12 :
            pixelmapInfo.pixelFormat = "NV12";
            break;
        case PIXEL_FORMAT_RGBA_1010102 :
            pixelmapInfo.pixelFormat = "RGBA_1010102";
            break;
        case PIXEL_FORMAT_YCBCR_P010 :
            pixelmapInfo.pixelFormat = "YCBCR_P010";
            break;
        case PIXEL_FORMAT_YCRCB_P010 :
            pixelmapInfo.pixelFormat = "YCRCB_P010";
            break;
        default :
            pixelmapInfo.pixelFormat = "Unknown";
            break;
    }
}

std::string ImageKnifeTaskInternal::GetDisplayPixelmapInfo() const
{
    return "Pixelmap Info: width:" + std::to_string(pixelmapInfo.width) +
           " height:" + std::to_string(pixelmapInfo.height) +
           " size:" + std::to_string(pixelmapInfo.size) +
           " format:" + pixelmapInfo.pixelFormat;
}

void ImageKnifeTaskInternal::SetIsAnimator()
{
    auto requestInternal = std::static_pointer_cast<ImageKnifeRequestInternal>(request_);
    if (requestInternal->IsPreload()) {
        // TODO 预加载遇到动图按什么处理?
        isAnimator_ = false;
        return;
    }

    auto imageNode = ImageKnifeInternal::GetInstance().GetImageNode(requestInternal->GetNodeId());
    if (imageNode == nullptr) {
        FatalError("Empty ImageNode When Set Animator Status");
        return;
    }

    isAnimator_ = imageNode->IsAnimator();
}

ImageFormat ImageKnifeTaskInternal::GetImageBufferFormat() const
{
    return imageBufferFormat_;
}

ImageSource *ImageKnifeTaskInternal::GetImageSource() const
{
    return imageSrc_;
}

ImageRequestType ImageKnifeTaskInternal::GetImageRequestType() const
{
    return type_;
}

std::shared_ptr<ImageKnifeRequest> ImageKnifeTaskInternal::GetImageKnifeRequest() const
{
    return request_;
}

void ImageKnifeTaskInternal::QueryImageBufferFormat()
{
    uint8_t *buffer;
    uint32_t length;

    if (product.imageBuffer != nullptr) {
        buffer = product.imageBuffer.get();
        length = product.imageLength;
    } else {
        EchoError("Empty Image Buffer (Query Image Format)");
        imageBufferFormat_ = ImageFormat::UNKNOWN;
        return;
    }

    imageBufferFormat_ = ImageKnifeInternal::GetInstance().fileTypeUtil.CheckImageFormat(buffer, length);

    if (imageBufferFormat_ == ImageFormat::GIF) {
        isAnimationImage_ = true;
    } else if (imageBufferFormat_ == ImageFormat::WEBP) {
        // webp 根据帧数判断图片是否为动图
        // ImageSource此处创建可能与Decode时是重复的，但避免耦合没有复用
        OH_ImageSourceNative *source = nullptr;
        Image_ErrorCode imgErrorCode = OH_ImageSourceNative_CreateFromData(buffer, length, &source);
        if (imgErrorCode != IMAGE_SUCCESS) {
            EchoError("Create ImageSource failed, error code: " + std::to_string(imgErrorCode));
            return;
        }
        
        uint32_t size = 0;
        imgErrorCode = OH_ImageSourceNative_GetFrameCount(source, &size);
        if (imgErrorCode != IMAGE_SUCCESS || size < 1) {
            EchoError("Get FrameCount Failed, error code: " + std::to_string(imgErrorCode));
        } else {
            isAnimationImage_ = true;
        }

        OH_ImageSourceNative_Release(source);
    }
}

} // end of namespace
